#ifndef PROBLEM_H_
#define PROBLEM_H_

#include <stdbool.h>
#include "vehicleState.h"
#include "gMatrix.h"
#include "operations.h"

/**il file comprende la struttura dati che rappresenta una soluzione, ovvero
 * l'insieme di tutti i percorsi eseguiti dai camion compresi tutti gli archi che sono stati soddisfatti.
 * Il file si prefigge inoltre di fornire delle primitive per la gestione della struttura Solution
 */

// ******************* STRUCTS ******************

/**rappresenta una soluzione del problema UCARPP*/
typedef struct Solution {
	/** K stati associati ai K veicoli del problema. */
	PvehicleState* states;
	/**un puntatore ad una cella di memoria che contiene il numero di camion usati nella soluzione*/
	int* K;
	/**indica la matrice contenente gli archi che sono stati soddisfatti*/
	PGMatrix gMatrix;
} Solution;
typedef Solution* Psolution;

// ******************** COSTRUTTORI *********************************
/**costruisce una nuova soluzione gia' provvista di tutti i puntatori necessari per poter usare le funzioni di questo header.
 * \pre
 * 	\li N e K non devono essere NULL
 * \post
 * 	\li una struttura Solution in memoria, oppure NULL se la memoria disponibile non è sufficiente
 *
 * @param K un puntatore ad una cella di memoria che contiene il numero di camion usati nella soluzione
 * @param N un puntatore ad una cella di memoria che contiene il numero di nodi presenti nel grafo
 * @return un puntatore che consente l'accesso ai campi della soluzione; viene mostrato un messaggio di errore in caso la memoria sia piena
 */
Psolution initSolution(int* K, int* N);

// ************************* FUNZIONI *******************************

/** TODO riciclare o cancellare
 * aggiunge l'arco passato come parametro nel percorso effettuato dal camion k. Per esempio, ipotizzando che
 * il percorso del camion sia:
 * <p>(0-4)(4-3)(3-6)(6-1)(1-0)</p>
 * l'arco da inserire sia 6-5. Dopo la funzione il percorso del camion sara':
 * <p>(0-4)(4-3)(3-6)(6-1)(1-0)(6-5)</p>
 * notare che la funzione rende il percorso assolutamente non corretto. Sara' la funzione chiamante che dovra' occuparsi di effettuare piu' chiamate
 * in modo da rendere il percorso accettabile.
 *
 * \pre
 * 	\li solution non deve essere NULL
 * 	\li id non deve essere NULL
 * 	\li id deve avere i<j
 * 	\li k>=0 e k<=K
 * \post
 * 	esistono varie casistiche:
 * 		\li se id era già contenuto nel percorso, il campo x di tale arco viene incrementato di 1
 * 		\li se id non era gia' presente, viene aggiunto al percorso con x=1
 * 		\li se _g e' TRUE k viene inserito nella matrice g soovrascrivendo il valore precedente
 *
 * @param solution indica la soluzione in cui inserire l'arco
 * @param k indica il camion
 * @param id indica l'edge da inserire. L'edge viene inserito in coda se non esiste nel percorso, mentre viene aumentato il valore del campo x se esiste gia'
 * @param edge indica le caratteristiche fisiche dell'arco da aggiungere
 * @param _g indica se l'arco deve essere soddisfatto (TRUE) oppure no (FALSE)
 */

/** TODO riciclare o cancellare
 * rimuove un arco all'interno della soluzione.
 * La funzione aggiorna inoltre anche il campo camionLengths della soluzione
 *
 * \pre
 * 	\li solution non deve essere NULL
 * 	\li k>=0 e k<=K
 * 	\li id non NULL
 * 	\li id deve avere i<j
 *
 * \post
 * 	ci sono varie casistiche:
 * 		\li se l'arco non era dentro il percorso non succede nulla
 * 		\li se l'arco era percorso piu' di una volta viene decremantato di 1 il campo x dell'arco
 * 		\li se l'arco era percorso solo una volta viene tolto dal percorso
 *
 * @param solution indica la soluzione da modificare
 * @param k indica il camion k da considerare
 * @param edge indica l'edge da togliere.
 */

/**
 * @param solution la soluzione che contiene il percorso del camion
 * @param k il camion di cui reperire il percorso
 * @return il percorso eseguito dal camion k nella soluzione solution
 */
PvehiclePath getVehiclePathInSolution(Psolution solution, int k);

/**
 * @param solution la soluzione che contiene il percorso del camion
 * @param k il camion di cui reperire il percorso
 * @return lo stato del camion k nella soluzione solution
 */
PvehicleState getVehicleStateInSolution(Psolution solution, int k);

/**ottiene il profitto totale ottenuto da questa soluzione
 *
 * \pre
 *  \li solution non NULL
 *
 * @param solution la soluzione di cui rilevare il profitto totale
 * @return il profitto totale offerto da tutti i camion in soluzione
 */
int getSolutionProfit(Psolution solution);

/**ottiene il tempo totale speso dai camion ottenuto da questa soluzione
 *
 * \pre
 *  \li solution non NULL
 *
 * @param solution la soluzione di cui rilevare il profitto totale
 * @return la somma dei tempi spesi da ciascun camion in soluzione
 */
int getSolutionTimeCost(Psolution solution);

/**ottiene il carico totale usato dai camion ottenuto da questa soluzione
 *
 * \pre
 *  \li solution non NULL
 *
 * @param solution la soluzione di cui rilevare il profitto totale
 * @return la somma dei carichi usati da ciascun camion in soluzione
 */
int getSolutionLoadCost(Psolution solution);

/**stampa il profitto totale ricavato dalla soluzione ps
 *
 * \pre
 *  \li ps non NULL
 *  \li f aperto in scrittura
 *
 * @param f il file su cui stampare il profitto ricavato
 * @param ps la soluzione da cui ricavare il profitto totale
 */
void printSolutionProfit(FILE* f, Psolution ps);

/**stampa la somma dei tempi di ciasun camion all'interno della soluzione ps
 *
 * \pre
 *  \li ps non NULL
 *  \li f aperto in scrittura
 *
 * @param f il file su cui stampare il profitto ricavato
 * @param ps la soluzione da cui ricavare il tempo totale
 */
void printSolutionTimeCost(FILE* f, Psolution ps);

/**stampa la somma dei carichi di ciasun camion all'interno della soluzione ps
 *
 * \pre
 *  \li ps non NULL
 *  \li f aperto in scrittura
 *
 * @param f il file su cui stampare il profitto ricavato
 * @param ps la soluzione da cui ricavare il carico totale
 */
void printSolutionLoadCost(FILE* f, Psolution ps);

/**Effettua una copia fisica della soluzione. La tabella mostra quali attributi vengono copiati fisicamente
 * e quali invece vengono copiati solo per indirizzo:
 *	<table>
 *		<tr>
 *		 <th>Campo</th>
 *		 <th>copia per</th>
 *		</tr>
 *		<tr>
 *		 <td>K</td>
 *		 <td>indirizzo</td>
 *		</tr>
 *		<tr>
 *		 <td>gMatrix</td>
 *		 <td>fisicamente</td>
 *		</tr>
 *		<tr>
 *		 <td>states</td>
 *		 <td>fisicamente</td>
 *		</tr>
 *	</table>
 *
 * \pre
 *  \li solution non NULL;
 *
 *
 * @param solution la soluzione di cui fare una copia
 * @return un nuova istanza di solution (che dovra' essere deallocata manualmente)
 */
Psolution cloneSolution(Psolution solution);

/**dealloca la soluzione passata dalla memoria.
 *
 * \pre
 *  \li psolution non NULL;
 * \post
 * 	\li lo spazio occupato dalla cella K (contenente il valore di K NON viene deallocato)
 *  \li lo spazio occupato dalla struttura Solution viene deallocato;
 *  \li spazio occupato dall'array states viene deallocato;
 *	\li lo spazio occupato dall'istanza di gMatrix viene deallocato;
 *	\li lo spazio occupato dalle istanze dell'array states viene deallocato;
 *
 * @param psolution la soluzione da deallocare
 */
void freeSolution(Psolution psolution);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~STAMPA~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** Wrappa printVehiclesStates aggiungendovi la lunghezza del percorso. TODO see l'altro to_do in struct Solution
 *
 * @param f il file su cui stampare la rappresentazione della soluzione
 * @param solution la soluzione da stampare
 * @param printMarked se stampare o no i valori marked. Siccome sono più di debug che di interesse utente, è giusto poterli inibire.
 */
void printSolution(FILE* f, Psolution solution);

/** Approccio Pat alla stampa della soluzione. Invece della GMatrix, invoca K printVehicleGathering() (cfr procedura)
 *
 * \pre
 *  \li f aperto in scrittura
 *  \li solution non NULL
 *
 * @param f il file su cui stampare la rappresentazione della soluzione
 * @param solution la soluzione da stampare
 */
void printVehicles(FILE* f, Psolution solution);

//TODO il prototipo di questa funzione dovrebbe essere FILE*,Psolution,int... altrimenti cosa ci fa n vehiclePath in solution???
/**Stampa una lista in formato printVehiclePath ma limitata agli archi raccolti. Per esempio se il percorso e'
 * <p>{(1 2)[gathered] (2 3) (3 4) (4 5)[gathered] (5 1)}</p>
 * dove per [gathered] si intende che il particolare camion k raccoglie l'arco il risultato sara'
 * <p>{(1 2) (4 5)}</p>
 *
 * \pre
 *  \li f aperto in scrittura
 *  \li p_path non NULL
 *  \li p_gMatrix non NULL
 *  \li k appartiene a [0;K[
 *
 * @param f il file su cui stampare
 * @param p_path il percorso da stampare
 * @param p_gMatrix la matrice dei raccoglimenti
 * @param k il camion usato
 */
void printVehicleGathering(FILE* f, PvehiclePath p_path, PGMatrix p_gMatrix, int k);

#endif /* PROBLEM_H_ */
